<template>
    <div class="container w-vw-100 h-vh-100 d-flex align-items-c justify-content-c flex-direction-c">
        <HeaderMenu @startGame = 'startGame' @chooseChess = 'chooseChess' @closeRoom = 'closeRoom' :roomID="roomID" :identity="identity" :isGameOvers="isGameOver" :isStartGames="isStartGame" :isMyTurns="isMyTurn" :myselfChesss="myself.chess" :himselfChesss="himself.chess" />
        <div class="w-90 h-80 d-flex align-items-c justify-content-b">
            <div class="w-10 h-100">
                <CompetitionInfo ref="CompetitionInfo" :round="this.myself.round" :isStart="isStartGame" :socket="socket" :chess="myself.chess" :pic="myself.pic"  :name="myself.userName + '(我)'"  :score="myself.score" action />
            </div>
            <div class="w-75 h-100 d-flex align-items-c justify-content-c">
                <Board2 ref="board" @changeRoundType="changeRoundType" @recordMatching="recordMatching" :isGameOver="isGameOver" :opposingBoard="opposingBoard" :roundType="isMyTurn" :chess="myself.chess" :socket="socket" :isStart="isStartGame" />
            </div>
            <div class="w-10 h-100">
                <CompetitionInfo :isStart="isStartGame" :socket="socket" :chess="himself.chess" :pic="himself.pic"  :name="himself.userName"  :score="himself.score" />
            </div>
        </div>
    </div>
</template>

<script>
import HeaderMenu from "@/components/gamematch/HeaderMenu.vue";
import CompetitionInfo from "@/components/gamematch/CompetitionInfo.vue";
import Board2 from '@/components/gamematch/Board2.vue';
import userAvatar from '@/assets/image/user-avatar.jpg'
import axios from "axios";
import {ElMessage, ElButton, ElMessageBox} from "element-plus";
import {checkGameOver} from "@/assets/js/checkerboard.js";
import { library } from '@fortawesome/fontawesome-svg-core'
import {faCoins} from "@fortawesome/free-solid-svg-icons/faCoins";
import {faFlag} from "@fortawesome/free-solid-svg-icons/faFlag";
library.add(faCoins, faFlag);
export default {
    components:{
        HeaderMenu,
        Board2,
        CompetitionInfo,
        ElButton,
    },
    data() {
        return {
            myself:{                //我的信息
                pic: userAvatar,
                userName: '虚位以待',
                score: 0,
                chess: 0,           //当前棋子颜色，1白棋，2黑棋
                uid: 0,             //我的uid
                round: 0,           //我进行了多少回合
                isStepBack: false,  //是否可以悔棋
            },
            himself:{               //对方信息
                pic: userAvatar,
                userName: '虚位以待',
                score: 0,
                chess: 0,           //当前棋子颜色，1白棋，2黑棋
                uid: 0,             //对方的uid
                round: 0,           //对方进行了多少回合
                isStepBack: false,  //是否可以悔棋
            },
            socket: null,
            roomID: '',         //房间ID
            roomClose: false,   //是否退出房间
            isStartGame: false,     //是否开始游戏
            identity: false,    //是否为房主
            round: 0,            //回合数
            isMyTurn: false,    //是否为我的回合
            opposingBoard: [],      //对方棋盘落子情况
            isGameOver: false,      //游戏是否结束
            board_md5: '',      //棋盘落子和房间号的加密
        }
    },
    methods: {
        init(){
            this.myself.chess = this.myself.round = this.himself.chess = this.himself.round = 0
            this.myself.isStepBack = this.himself.isStepBack = false;
            this.board_md5 = '';
        },
        /**
         * 选择旗子
         */
        chooseChess(chess){
            if(chess === this.myself.chess || this.isStartGame){
                return;
            }
            this.myself.chess = chess;
            this.socket.send(JSON.stringify({
                mode: 'chooseChess',
                room_id: this.$common.getSessionStorageValues('roomInfo.room_id'),
                uid: this.$common.getSessionStorageValues('userLoginInfo.id'),
                chess: chess,
            }));
        },
        /**
         * 开始游戏
         */
        async startGame(){
            if(this.myself.chess === 0){
                ElMessage({
                    message: '请选择棋子',
                    type: 'warning',
                })
                return
            }
            if(this.himself.uid === 0){
                ElMessage({
                    message: '不足两人无法开始游戏',
                    type: 'warning',
                })
                return
            }
            if(this.himself.chess === 0){
                ElMessage({
                    message: '请等待对方选择棋子',
                    type: 'warning',
                })
                return
            }
            if(this.myself.chess === this.himself.chess){
                ElMessage({
                    message: '不能选择相同颜色的棋子哦!请重新选择',
                    type: 'warning',
                })
                return
            }
            this.$refs.board.gridData = Array(this.grid).fill(Array(this.grid).fill(0));
            //将双方选择的棋子保存
            const response = await axios.post('/api/savechesscolor', {room_id: this.$common.getSessionStorageValues('roomInfo.room_id'), my_chess: this.myself.chess, him_chess: this.himself.chess, him_uid: this.himself.uid}, {
                headers: {
                    token: this.$common.getSessionStorageValues('tokenData.token'),
                    refreshtoken: this.$common.getSessionStorageValues('tokenData.refreshtoken')
                }
            });
            if (response.data.code === 200 && response.status === 200) {
                this.socket.send(JSON.stringify({
                    mode: 'startGame',
                    room_id: this.$common.getSessionStorageValues('roomInfo.room_id'),
                    uid: this.$common.getSessionStorageValues('userLoginInfo.id'),
                    chess: this.myself.chess,
                    board: this.$refs.board.gridData,
                }));
            } else {
                ElMessage({
                    message: response.data.msg ? response.data.msg : '错误',
                    type: 'warning',
                })
            }

        },
        /**
         * 关闭房间
         * @returns {Promise<void>}
         */
        async closeRoom(flag = false){
            if (this.roomClose) {
                return
            }
            this.roomClose = true;
            if(this.isStartGame){
                ElMessageBox.confirm(
                    '游戏已经开始了，还要退出房间吗？',
                    '退出房间',
                    {
                        confirmButtonText: '退出',
                        cancelButtonText: '不退出',
                        type: 'warning',
                        closeOnClickModal : false,
                        closeOnPressEscape : false,
                    }
                )
                    .then(async () => {
                        await this.exitRoom(flag);
                    })
                    .catch(() => {
                        this.roomClose = false;
                    })
            }else {
                await this.exitRoom(flag);
            }
        },
        disconnectSocket(){
            this.socket.send(JSON.stringify({
                mode: 'leaveRoom',
                room_id: this.$common.getSessionStorageValues('roomInfo.room_id'),
                identity: this.$common.getSessionStorageValues('roomInfo.identity'),
                uid: this.$common.getSessionStorageValues('userLoginInfo.id'),
            }));
            this.socket.close();
        },
        /**
         * 连接socket
         */
        socketConnected(){
            // this.socket = new WebSocket('ws://192.168.124.5:9988');
            this.socket = new WebSocket('ws://' + import.meta.env.VITE_WEBSOCKET_IP + ':' + import.meta.env.VITE_WEBSOCKET_PORT);
            this.socket.onopen = () => {
                // console.log("连接成功");
                this.socket.send(JSON.stringify({
                    mode: 'joinRoom',
                    identity: this.$common.getSessionStorageValues('roomInfo.identity'),
                    uid: this.$common.getSessionStorageValues('userLoginInfo.id'),
                    room_id: this.roomID,
                    info: {
                        uid: this.$common.getSessionStorageValues('userLoginInfo.id'),
                        username: this.$common.getSessionStorageValues('userLoginInfo.username'),
                        score: this.$common.getSessionStorageValues('userLoginInfo.score'),
                    }
                }));
            };
            this.socket.onerror = () => {
                // console.log("连接失败");
            }
            this.socket.onmessage = async (e) => {
                try {
                    const data = JSON.parse(e.data);
                    // console.log(data);
                    switch(data.type){
                        case 'onlyMsg':         //仅收到消息
                            if('msgData' in data && Object.keys(data.msgData).length > 0){
                                switch (data.msgData.messageBoxType){
                                    case 'box':
                                        await ElMessageBox.alert(data.msg, data.msgData.title, {
                                            confirmButtonText: '关闭',
                                        })
                                        break;
                                    case 'confirm':
                                        ElMessageBox.confirm(
                                            data.msg,
                                            data.msgData.title,
                                            {
                                                confirmButtonText: '同意',
                                                cancelButtonText: '不同意',
                                                type: 'warning',
                                                closeOnClickModal : false,
                                                closeOnPressEscape : false,

                                            }
                                        )
                                            .then(async () => {
                                                if (data.msgData.type === 'stepBack') {       //发送悔棋结果--同意悔棋
                                                    await this.executeStepBack();
                                                } else if (data.msgData.type === 'requestingGameTie') {        //发送对局结果--平局
                                                    await this.theGameOver(3, {type: 'requestingGameTie'});
                                                }
                                            })
                                            .catch(() => {
                                                if(data.msgData.type === 'stepBack') {      //发送悔棋结果--不同意悔棋
                                                    this.socket.send(JSON.stringify({
                                                        mode: 'stepBackAction',
                                                        stepBackType: 2,
                                                        room_id: this.$common.getSessionStorageValues('roomInfo.room_id'),
                                                        uid: this.$common.getSessionStorageValues('userLoginInfo.id'),
                                                    }))
                                                }else if(data.msgData.type === 'requestingGameTie'){    //发送对局结果--不同意平局
                                                    this.socket.send(JSON.stringify({
                                                        mode: 'requestingGameTieAction',
                                                        room_id: this.$common.getSessionStorageValues('roomInfo.room_id'),
                                                        uid: this.$common.getSessionStorageValues('userLoginInfo.id'),
                                                    }))
                                                }
                                            })
                                        break;
                                }
                            }else{
                                ElMessage({
                                    message: data.msg,
                                    type: data.msgType ? data.msgType : 'warning',
                                })
                            }

                            break;
                        case 'usersInfos':          //收到玩家/所有玩家信息
                            if('socketData' in data && Object.keys(data['socketData']).length > 0) {
                                for (let key in data['socketData']) {
                                    if (this.$common.getSessionStorageValues('userLoginInfo.id') === data['socketData'][key]['uid'] || typeof data['socketData'][key] !== 'object') {
                                        continue;
                                    }
                                    this.himself.uid = data['socketData'][key]['uid'];
                                    this.himself.userName = data['socketData'][key]['username'];
                                    this.himself.score = data['socketData'][key]['score'];
                                }
                            }
                            break;
                        case 'leaveRoom':           //收到其他玩家离开游戏的消息
                            this.himself.userName = '虚位以待';
                            this.himself.score = 0;
                            break;
                        case 'closeRoom':       //房主关闭房间
                            await this.closeRoom();
                            break;
                        case 'chooseChess':     //获取别人的棋子颜色
                            this.himself.chess = data.socketData.oppositeChess;
                            break;
                        case 'chooseChessAll':     //获取所有人的棋子颜色
                            if( ('socketData' in data && Object.keys(data['socketData']).length > 0) && ('oppositeChess' in data['socketData'] && Object.keys(data['socketData']['oppositeChess']).length > 0) ){

                            }
                            for (let key in data['socketData']['oppositeChess']){
                                if(this.$common.getSessionStorageValues('userLoginInfo.id') === key){
                                    continue;
                                }
                                this.himself.chess = +(data['socketData']['oppositeChess'][key]);
                            }
                            break;
                        case 'startGame':       //收到房主的开始游戏
                            this.isStartGame = true;
                            this.isGameOver = false;
                            this.isMyTurn = this.myself.chess === 1;
                            this.$refs.CompetitionInfo.requestingGameTieButton.disabled = this.$refs.CompetitionInfo.loserButton.disabled = false;
                            this.$refs.board.init();
                            break;
                        case 'board':           //对方棋盘落子
                            this.opposingBoard = data.socketData;
                            this.board_md5 = data.boardMd5;
                            this.isMyTurn = data.chess === this.myself.chess;
                            this.round++;
                            this.$refs.CompetitionInfo.stepBackButton.disabled = true;
                            break;
                        case 'processingResults':       //对局结果
                            this.isGameOver = true;
                            this.isStartGame = false;
                            this.$refs.CompetitionInfo.stepBackButton.disabled = this.$refs.CompetitionInfo.requestingGameTieButton.disabled = this.$refs.CompetitionInfo.loserButton.disabled = true;
                            //比赛结束3s后清空棋盘
                            setTimeout(() => {
                                this.$refs.board.gridData = Array(this.grid).fill(Array(this.grid).fill(0));
                            }, 3000)
                            break;
                        case 'stepBackAction':      //执行悔棋操作，恢复上一次落子的棋盘
                            this.round--;
                            if(data.socketData.chess === this.myself.chess){
                                this.isMyTurn = true;
                                this.myself.round--;
                            }else{
                                this.isMyTurn = false;
                            }
                            this.opposingBoard = data.socketData.board;
                            break;
                        case 'stepBackActionNotice':        //仅收到悔棋的通知后操作
                            this.$refs.CompetitionInfo.stepBackButton.loading = false;
                            this.$refs.CompetitionInfo.stepBackButton.disabled = this.myself.isStepBack = true;
                            break;
                        case 'requestingGameTieActionNotice':       //仅收到求和的是否同意的通知后操作
                            this.$refs.CompetitionInfo.requestingGameTieButton.loading = false;
                            this.$refs.CompetitionInfo.requestingGameTieButton.disabled = true;
                            break;
                        case 'exitTheGame':     //对方在游戏进行中退出了游戏
                            await this.theGameOver(4, {type: 'exitTheGame'});
                            break;
                        case 'timeOutLoser':     //对方在游戏进行中规定时间内不落子/对方掉线了
                            await this.theGameOver(4, {type: 'timeOutLoser'});
                            break;
                    }
                } catch (error) {
                    // console.log(e.data);
                }
            };

            this.socket.onclose = async (e) => {
                // console.log(e);
                // const response = await axios.post('/api/aaa', {}, {
                //     headers: {
                //         token: this.$common.getSessionStorageValues('tokenData.token'),
                //         refreshtoken: this.$common.getSessionStorageValues('tokenData.refreshtoken')
                //     }
                // });
                // if (response.data.code === 200 && response.status === 200) {
                //
                // } else {
                //     ElMessage({
                //         message: response.data.msg ? response.data.msg : '错误',
                //         type: 'warning',
                //     })
                // }
            }
        },
        /**
         * 修改自身状态 和 增加过去回合数
         */
        changeRoundType() {
            this.$refs.CompetitionInfo.requestingGameTieButton.disabled = false;
            this.isMyTurn = false;
            this.round++;
            this.myself.round++;
            this.$refs.CompetitionInfo.stepBackButton.disabled = this.myself.isStepBack ? this.myself.isStepBack : this.myself.round < 1;
        },

        /**
         * 记录落子情况
         * @param gridData {array}  棋盘参数
         * @param chess {number}    落子颜色
         * @param result {number}   游戏结束方式，1白棋，2黑棋，3平局，4对方掉线/离开房间
         * @returns {Promise<void>}
         */
        async recordMatching(gridData, chess, result){
            if(checkGameOver(gridData.data, [gridData.x, gridData.y], gridData.data[gridData.y][gridData.x])){
                this.isGameOver = true;
            }
            const response = await axios.post('/api/recordmatching', {room_id: this.$common.getSessionStorageValues('roomInfo.room_id'), board: JSON.stringify(gridData.data), result: this.isGameOver ? 1 : 0, chess: chess }, {
                headers: {
                    token: this.$common.getSessionStorageValues('tokenData.token'),
                    refreshtoken: this.$common.getSessionStorageValues('tokenData.refreshtoken')
                }
            });
            if (response.data.code === 200 && response.status === 200) {
                this.socket.send(JSON.stringify({
                    mode: 'matching',
                    room_id: this.$common.getSessionStorageValues('roomInfo.room_id'),
                    uid: this.$common.getSessionStorageValues('userLoginInfo.id'),
                    board: gridData.data,
                    chess: chess,
                    board_md5: response.data.data.board_md5 ? response.data.data.board_md5 : '',
                }))
            } else {
                ElMessage({
                    message: response.data.msg ? response.data.msg : '错误',
                    type: 'warning',
                })
            }
            this.isGameOver && await this.theGameOver(result);
        },
        /**
         * 游戏结束
         * @param result {number}       游戏结束方式，1白棋，2黑棋，3平局，4对方掉线/离开房间
         * @param socketData {object}   发送socket的额外参数
         * @returns {Promise<void>}
         */
        async theGameOver(result, socketData = {}){
            const response = await axios.post('/api/processingresults', {room_id: this.$common.getSessionStorageValues('roomInfo.room_id'), result: result}, {
                headers: {
                    token: this.$common.getSessionStorageValues('tokenData.token'),
                    refreshtoken: this.$common.getSessionStorageValues('tokenData.refreshtoken')
                }
            });
            if (response.data.code === 200 && response.status === 200) {
                this.socket.send(JSON.stringify({
                    mode: 'processingResults',
                    room_id: this.$common.getSessionStorageValues('roomInfo.room_id'),
                    uid: this.$common.getSessionStorageValues('userLoginInfo.id'),
                    ...socketData,
                }))
            } else {
                ElMessage({
                    message: response.data.msg ? response.data.msg : '错误',
                    type: 'warning',
                })
            }
        },
        /**
         * 执行悔棋请求
         * @returns {Promise<void>}
         */
        async executeStepBack(){
            const response = await axios.post('/api/stepback', {
                room_id: this.$common.getSessionStorageValues('roomInfo.room_id'),
                board_md5: this.board_md5
            }, {
                headers: {
                    token: this.$common.getSessionStorageValues('tokenData.token'),
                    refreshtoken: this.$common.getSessionStorageValues('tokenData.refreshtoken')
                }
            });
            if (response.data.code === 200 && response.status === 200) {
                this.socket.send(JSON.stringify({
                    mode: 'stepBackAction',
                    stepBackType: 1,
                    room_id: this.$common.getSessionStorageValues('roomInfo.room_id'),
                    uid: this.$common.getSessionStorageValues('userLoginInfo.id'),
                }))
            } else {
                ElMessage({
                    message: response.data.msg ? response.data.msg : '错误',
                    type: 'warning',
                })
            }
        },
        /**
         * 退出房间
         * @param flag {boolean}        是否是主动点击退出房间按钮
         * @returns {Promise<void>}
         */
        async exitRoom(flag = false){
            if (this.socket && this.socket.readyState === WebSocket.OPEN) {
                this.disconnectSocket();
            }
            /**
             * 1. 玩家主动点击退出房间，需要发送退出房间接口
             * 2. 房主点击退出房间，需要发送退出房间接口，但是玩家收到socket后被通知，不需要发送退出房间接口，直接断开链接
             */
            if (flag || (flag === false && this.$common.getSessionStorageValues('roomInfo.identity') === 1)) {
                const response = await axios.post('/api/leaveroom', {
                    room_id: this.$common.getSessionStorageValues('roomInfo.room_id'),
                    identity: this.$common.getSessionStorageValues('roomInfo.identity')
                }, {
                    headers: {
                        token: this.$common.getSessionStorageValues('tokenData.token'),
                        refreshtoken: this.$common.getSessionStorageValues('tokenData.refreshtoken')
                    }
                });
                if (response.data.code === 200 && response.status === 200) {
                    this.$common.removeSessionStorageValues('roomInfo');
                    this.$router.replace('/');
                } else {
                    ElMessage({
                        message: response.data.msg ? response.data.msg : '错误',
                        type: 'warning',
                    })
                }
            } else {
                this.$common.removeSessionStorageValues('roomInfo');
                this.$router.replace('/');
            }
        },
    },
    mounted() {
        this.socketConnected();
    },
    beforeUnmount() {
        // this.closeRoom();
    },
    beforeCreate() {
        if(!this.$common.getSessionStorageValues('roomInfo')){
            this.$router.replace('/');
        }
    },
    beforeMount() {
        this.myself.uid = this.$common.getSessionStorageValues('userLoginInfo.id');
        this.myself.userName = this.$common.getSessionStorageValues('userLoginInfo.username');
        this.myself.score = this.$common.getSessionStorageValues('userLoginInfo.score');
        this.roomID = this.$common.getSessionStorageValues('roomInfo.room_id');
        this.identity = this.$common.getSessionStorageValues('roomInfo.identity') === 1;
    },
}

</script>

<style scoped lang="scss">
.container{
    //width: var(--containerWidth, 0);
    //height: var(--containerHeight, 0);
}
</style>